/**
 *  \file monAirportRhapsodyDr.c (implementation file)
 *
 *  \brief Problem name: Airport rhapsody.
 *
 *  \brief Concept: António Rui Borges
 *
 *  Synchronization based on monitors.
 *  Both threads and the monitor are implemented using the pthread library which enables the creation of a
 *  monitor of the Lampson / Redell type.
 *
 *  Definition of the operations carried out by the bus driver thread:
 *     \li has day's work ended
 *     \li announcing bus boarding
 *     \li go to departure terminal
 *     \li park the bus and let passengers off
 *     \li go to arrival terminal
 *     \li park the bus.
 *
 *  \author António Rui Borges - December 2013
 */

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <pthread.h>
#include <errno.h>

#include "probConst.h"
#include "probDataStruct.h"
#include "cam.h"
#include "queue.h"
#include "logging.h"
#include "monAirportRhapsodyIDS.h"

/** \brief logging file name */
extern char nFic[51];

/** \brief bus driver thread return status */
extern int statusDR;

/**
 *  \brief Has days work ended.
 *
 *  The bus driver keeps waiting for passengers to transfer until his day's work has come to an end. He only proceeds
 *  if his day's work is indeed finished or there are passengers needing to be serviced.
 *
 *  No state should be saved.
 *
 *  \return \c true, if the day has come to the end
 *  \return \c false, if there are passengers needing to be serviced
 */

bool hasDaysWorkEnded (void)
{
  if ((statusDR = pthread_mutex_lock (&accessCR)) != 0)                                             /* enter monitor */
     { errno = statusDR;                                                                      /* save error in errno */
       perror ("error on entering the monitor (DR)");
       statusDR = EXIT_FAILURE;
       pthread_exit (&statusDR);
     }
  pthread_once (&init, initialization);                                              /* internal data initialization */

             /* insert youy code here */

  if ((statusDR = pthread_mutex_unlock (&accessCR)) != 0)                                            /* exit monitor */
     { errno = statusDR;                                                                      /* save error in errno */
       perror ("error on exiting monitor (DR)");
       statusDR = EXIT_FAILURE;
       pthread_exit (&statusDR);
     }

  return true;
}

/**
 *  \brief Announcing bus boarding.
 *
 *  The bus driver checks if the queue is empty. If it is, he issues an error message.
 *  He then proceeds to summon passengers in the queue to board the bus. If some passenger identity is unknown, he
 *  issues an error message. He finally waits for the boarding to be complete.
 *
 *  No state should be saved.
 */

void announcingBusBoarding (void)
{
  if ((statusDR = pthread_mutex_lock (&accessCR)) != 0)                                             /* enter monitor */
     { errno = statusDR;                                                                      /* save error in errno */
       perror ("error on entering the monitor (DR)");
       statusDR = EXIT_FAILURE;
       pthread_exit (&statusDR);
     }
  pthread_once (&init, initialization);                                              /* internal data initialization */

             /* insert youy code here */

  if ((statusDR = pthread_mutex_unlock (&accessCR)) != 0)                                            /* exit monitor */
     { errno = statusDR;                                                                      /* save error in errno */
       perror ("error on exiting monitor (DR)");
       statusDR = EXIT_FAILURE;
       pthread_exit (&statusDR);
     }
}

/**
 *  \brief Go to departure terminal.
 *
 *  The bus driver takes the bus to the departure transfer terminal.
 *
 *  State should be saved.
 */

void goToDepartureTerminal (void)
{
  if ((statusDR = pthread_mutex_lock (&accessCR)) != 0)                                             /* enter monitor */
     { errno = statusDR;                                                                      /* save error in errno */
       perror ("error on entering the monitor (DR)");
       statusDR = EXIT_FAILURE;
       pthread_exit (&statusDR);
     }
  pthread_once (&init, initialization);                                              /* internal data initialization */

             /* insert youy code here */

  if ((statusDR = pthread_mutex_unlock (&accessCR)) != 0)                                            /* exit monitor */
     { errno = statusDR;                                                                      /* save error in errno */
       perror ("error on exiting monitor (DR)");
       statusDR = EXIT_FAILURE;
       pthread_exit (&statusDR);
     }
}

/**
 *  \brief Park the bus and let passengers off.
 *
 *  The bus driver checks if the bus is empty or overcrowded. If it is, he issues an error message.
 *  He then proceeds to summon passengers in the bus to exit. If some passenger identity is unknown, he
 *  issues an error message. He finally waits for the exit to be complete.
 *
 *  State should be saved.
 */

void parkTheBusAndLetPassOff (void)
{
  if ((statusDR = pthread_mutex_lock (&accessCR)) != 0)                                             /* enter monitor */
     { errno = statusDR;                                                                      /* save error in errno */
       perror ("error on entering the monitor (DR)");
       statusDR = EXIT_FAILURE;
       pthread_exit (&statusDR);
     }
  pthread_once (&init, initialization);                                              /* internal data initialization */

             /* insert youy code here */

  if ((statusDR = pthread_mutex_unlock (&accessCR)) != 0)                                            /* exit monitor */
     { errno = statusDR;                                                                      /* save error in errno */
       perror ("error on exiting monitor (DR)");
       statusDR = EXIT_FAILURE;
       pthread_exit (&statusDR);
     }
}

/**
 *  \brief Go to arrival terminal.
 *
 *  The bus driver takes the bus back to the arrival transfer terminal.
 *
 *  State should be saved.
 */

void goToArrivalTerminal (void)
{
  if ((statusDR = pthread_mutex_lock (&accessCR)) != 0)                                             /* enter monitor */
     { errno = statusDR;                                                                      /* save error in errno */
       perror ("error on entering the monitor (DR)");
       statusDR = EXIT_FAILURE;
       pthread_exit (&statusDR);
     }
  pthread_once (&init, initialization);                                              /* internal data initialization */

             /* insert youy code here */

  if ((statusDR = pthread_mutex_unlock (&accessCR)) != 0)                                            /* exit monitor */
     { errno = statusDR;                                                                      /* save error in errno */
       perror ("error on exiting monitor (DR)");
       statusDR = EXIT_FAILURE;
       pthread_exit (&statusDR);
     }
}

/**
 *  \brief Park the bus.
 *
 *  The parks the bus at the arrival transfer terminal.
 *
 *  State should be saved.
 */

void parkTheBus (void)
{
  if ((statusDR = pthread_mutex_lock (&accessCR)) != 0)                                             /* enter monitor */
     { errno = statusDR;                                                                      /* save error in errno */
       perror ("error on entering the monitor (DR)");
       statusDR = EXIT_FAILURE;
       pthread_exit (&statusDR);
     }
  pthread_once (&init, initialization);                                              /* internal data initialization */

             /* insert youy code here */

  if ((statusDR = pthread_mutex_unlock (&accessCR)) != 0)                                            /* exit monitor */
     { errno = statusDR;                                                                      /* save error in errno */
       perror ("error on exiting monitor (DR)");
       statusDR = EXIT_FAILURE;
       pthread_exit (&statusDR);
     }
}
